package com.ebei.admin.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ebei.admin.common.constant.Constants;
import com.ebei.admin.common.util.AuthRealm;
import com.ebei.admin.common.util.CommonUtil;
import com.ebei.admin.common.util.TreeUtil;
import com.ebei.admin.mapper.*;
import com.ebei.admin.model.dto.OrgDTO;
import com.ebei.admin.model.dto.OrgRelation;
import com.ebei.admin.model.dto.OrgTree;
import com.ebei.admin.model.entity.*;
import com.ebei.admin.service.*;
import com.ebei.common.constant.CommonConstant;
import com.ebei.common.util.Query;
import com.ebei.common.util.Result;
import com.xiaoleilu.hutool.bean.BeanUtil;
import com.xiaoleilu.hutool.convert.Convert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 部门服务实现类
 *
 * @author crazypenguin
 * @version 1.0
 * @created 2018/4/17
 */
@Service
public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> implements SysOrgService {

    @Autowired
    private SysOrgMapper sysOrgMapper;
    @Autowired
    private SysParkMapper sysParkMapper;
    @Autowired
    private SysCompanyMapper sysCompanyMapper;
    @Autowired
    private SysOrgRoleUserMapper sysOrgRoleUserMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysProjectMapper sysProjectMapper;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private SysDictDetailService sysDictDetailService;
    @Autowired
    private SysCompanyService sysCompanyService;
    @Autowired
    private SysParkService sysParkService;
    @Autowired
    private SysProjectService sysProjectService;
    @Autowired
    private PositionService positionService;

    public SysOrgServiceImpl() {
    }

    /**
     * 级别号、排序号赋值（新增组织架构用）
     *
     * @return
     */
    private SysOrg getLevelNum(SysOrg dept) {
        // 获取父节点
        SysOrg conditon1 = new SysOrg();
        conditon1.setOrgId(dept.getParentId());
        conditon1.setDelFlag(CommonConstant.STATUS_NORMAL);
        SysOrg pSysOrg = super.selectOne(new EntityWrapper<>(conditon1));

        // 获取同级节点
        SysOrg conditon2 = new SysOrg();
        conditon2.setParentId(dept.getParentId());
        conditon2.setDelFlag(CommonConstant.STATUS_NORMAL);
        List<SysOrg> subDepts = super.selectList(new EntityWrapper<>(conditon2));

        // 获取同级节点最大levelNum以及最大orderNum
        // 防止删除中间的节点之后 出现节点levelNum重复的现象
        Map<String, Object> params = new HashMap<>();
        params.put("parentId", dept.getParentId());
        Map result = sysOrgMapper.getMaxNumByParams(params);

        // 如果是顶级节点(10000)
        if (pSysOrg == null) {
            if (subDepts == null || subDepts.size() == 0) {
                dept.setOrderNum(1);
                dept.setLevelNum(CommonConstant.ORGTYPE_MAX_SIZE);
            } else {
                if (result != null) {
                    int maxOrderNum = Integer.valueOf(result.get("orderNum").toString());
                    dept.setOrderNum(maxOrderNum + 1);
                    int maxLevelNum = Integer.parseInt(result.get("levelNum").toString());
                    dept.setLevelNum(String.valueOf(maxLevelNum + 1));
                }
            }
        } else {
            // 没有子节点(1000010000)
            if (subDepts == null || subDepts.size() == 0) {
                dept.setLevelNum(pSysOrg.getLevelNum() + CommonConstant.ORGTYPE_MAX_SIZE);
                dept.setOrderNum(1);
            }
            // 有子节点(1000010001、1000010002)
            else {
                if (result != null) {
                    int maxOrderNum = Integer.valueOf(result.get("orderNum").toString());
                    dept.setOrderNum(maxOrderNum + 1);
                    String maxLevelNum = result.get("levelNum").toString();
                    // 分别截取后5位 和 前面部分
                    String tempLevelNum1 = maxLevelNum.substring(0, maxLevelNum.length() - CommonConstant.ORGTYPE_MAX_SIZE.length());
                    String tempLevelNum2 = maxLevelNum.substring(maxLevelNum.length() - CommonConstant.ORGTYPE_MAX_SIZE.length());
                    int tempLevel = Integer.valueOf(tempLevelNum2).intValue() + 1;
                    dept.setLevelNum(tempLevelNum1 + String.valueOf(tempLevel));
                }
            }
        }
        return dept;
    }

    /**
     * 获取最大levelNum以及orderNum
     *
     * @param params
     * @return
     */
    private Map<String, Object> getMaxNumByParams(Map<String, Object> params) {
        return sysOrgMapper.getMaxNumByParams(params);
    }

    /**
     * 查询子节点
     *
     * @param orgId
     * @return
     */
    @Override
    public List<SysOrg> getChildren(Integer orgId) {
        SysOrg sysOrg = this.selectById(orgId);
        return sysOrgMapper.selectChildren(sysOrg.getLevelNum());
    }

    /**
     * 查询部门树
     *
     * @param sysDeptEntityWrapper
     * @return 树
     */
    @Override
    public List<OrgTree> selectListTree(EntityWrapper<SysOrg> sysDeptEntityWrapper) {
        return getDeptTree(this.selectList(sysDeptEntityWrapper), 0);
    }

    /**
     * 查询部门列表
     *
     * @param sysDeptEntityWrapper sysDeptEntityWrapper
     * @return 部门列表
     */
    private List<SysOrg> selectDeptDtoList(EntityWrapper<SysOrg> sysDeptEntityWrapper) {
        return sysOrgMapper.selectDeptDtoList(sysDeptEntityWrapper.getEntity().getDelFlag());
    }

    @Override
    public List<OrgTree> getDeptTree(List<SysOrg> sysOrgs, Integer root) {
        List<OrgTree> orgTrees = new ArrayList<>();
        OrgTree node;
        for (SysOrg sysOrg : sysOrgs) {
            node = new OrgTree();
            node.setName(sysOrg.getName());
            node.setId(sysOrg.getOrgId());
            node.setParentId(sysOrg.getParentId());
            // SysDictDetail sysDictDetail = sysDictDetailService.selectById(sysOrg.getType());
            node.setType(sysOrg.getType());
            node.setOpen(Boolean.FALSE);

            orgTrees.add(node);
        }
        return TreeUtil.bulid(orgTrees, root);
    }

    @Override
    public Result getOrgType(Integer userId) {

        Result<List<SysDictDetail>> result = new Result<>();
        // 查询字典项
        SysDict condition = new SysDict();
        condition.setDictCode(CommonConstant.ORG_TYPE_CODE);
        condition.setDelFlag(CommonConstant.STATUS_NORMAL);
        SysDict sysDict = sysDictService.selectOne(new EntityWrapper<>(condition));
        // 查询字典详情
        EntityWrapper<SysDictDetail> ew = new EntityWrapper<>();
        ew.eq("dict_id", sysDict.getDictId());
        ew.eq("del_flag", CommonConstant.STATUS_NORMAL);

        // 超级管理员可看全部，非超级管理员按园区企业区分
        if (!sysRoleService.hasPermission(userId, Constants.SUPER_ADMIN)) {
            SysUser sysUser = sysUserService.selectById(userId);
            List<Integer> tempDetailIds = new ArrayList<>();
            // 政府用户不能看到园区
            if (Constants.TYPE_GOV.equals(sysUser.getType())) {
                tempDetailIds.add(CommonConstant.ORGTYPE_SPARK);
            }
            // 企业用户不能看到园区、企业
            else if (Constants.TYPE_COM.equals(sysUser.getType())) {
                tempDetailIds.add(CommonConstant.ORGTYPE_SPARK);
                tempDetailIds.add(CommonConstant.ORGTYPE_COMP);
            }
            ew.notIn("id", tempDetailIds);
        }

        List<SysDictDetail> sysDictDetailList = sysDictDetailService.selectList(ew);

        result.setData(sysDictDetailList);
        result.setErrorMessage("获取成功");
        result.setErrorCode(Result.SUCCESS);

        return result;
    }

    @Override
    @Transactional
    public Result cascadeInsert(OrgDTO orgDTO) {
        // 新增组织架构
        SysOrg sysOrg = new SysOrg();
        orgDTO.setPassword(CommonUtil.ENCODER.encode(CommonConstant.DEFAULT_PASSWORD));
        orgDTO.setCreateTime(new Date());
        orgDTO.setUpdateTime(new Date());
        orgDTO.setDelFlag(CommonConstant.STATUS_NORMAL);
        BeanUtils.copyProperties(orgDTO, sysOrg);
        // 组织架构类型
        Integer type = orgDTO.getType();
        try {
            /* 新增组织 */
            sysOrg = getLevelNum(sysOrg);
            sysOrgMapper.insertReturnId(sysOrg);
            Integer orgId = sysOrg.getOrgId();
            /* 判断是否需要新增超管 */
            if (needCreate(type)) {
                /* 新增管理人员  */
                SysUser sysUser = new SysUser();
                String userName = sysOrgMapper.selectById(orgId).getName() + "管理员";
                sysUser.setUserName(userName);
                sysUser.setUserAccount(orgDTO.getAdminAccount());
                sysUser.setPassword(orgDTO.getPassword());
                sysUser.setCreateTime(new Date());
                sysUser.setAvatar(Constants.DEFAULT_AVATAR);
                sysUser.setDelFlag(CommonConstant.STATUS_NORMAL);
                sysUser.setSex(Constants.DEFAULT_SEX);
                sysUser.setSalt(CommonConstant.DEFAULT_SALT);
                // 如果是项目 orgId指定为企业
                if(isProject(type)){
                    sysUser.setOrgId(getTypedOrgByOrgId(orgId,CommonConstant.ORGTYPE_COMP).getOrgId());
                }else{
                    sysUser.setOrgId(orgId);
                }
                sysUser.setType(getUserType(type));
                sysUserMapper.insertReturnId(sysUser);
                /* 新增user和岗位关联 */
                SysOrgRoleUser sysOrgRoleUser = new SysOrgRoleUser();
                sysOrgRoleUser.setUserId(sysUser.getUserId());
                // 公司管理员
                if (isCompany(type)) {
                    SysCompany sysCompany = new SysCompany();
                    BeanUtil.copyProperties(orgDTO, sysCompany);
                    sysCompany.setOrgId(orgId);
                    sysCompany.setPassword(orgDTO.getPassword());
                    sysCompany.setDelFlag(CommonConstant.STATUS_NORMAL);
                    sysCompany.setParkId(this.getTypedOrgByOrgId(orgId,CommonConstant.ORGTYPE_SPARK).getOrgId());
                    sysCompanyMapper.insert(sysCompany);
                    sysOrgRoleUser.setPositionId(getAdminPosition(Constants.COMPANY_ADMIN));
                    sysOrgRoleUserMapper.insert(sysOrgRoleUser);
                } else if (isPark(type)) {
                    SysPark sysPark = new SysPark();
                    BeanUtil.copyProperties(orgDTO, sysPark);
                    sysPark.setOrgId(orgId);
                    sysPark.setPassword(orgDTO.getPassword());
                    sysPark.setDelFlag(CommonConstant.STATUS_NORMAL);
                    sysParkMapper.insert(sysPark);
                    sysOrgRoleUser.setPositionId(getAdminPosition(Constants.PARK_ADMIN));
                    sysOrgRoleUserMapper.insert(sysOrgRoleUser);
                } else if (isProject(type)) {
                    SysProject sysProject = new SysProject();
                    BeanUtil.copyProperties(orgDTO, sysProject);
                    sysProject.setOrgId(sysOrg.getOrgId());
                    sysProject.setPassword(orgDTO.getPassword());
                    sysProject.setDelFlag(CommonConstant.STATUS_NORMAL);
                    sysProject.setCompanyId(this.getTypedOrgByOrgId(sysOrg.getOrgId(),CommonConstant.ORGTYPE_COMP).getOrgId());
                    sysProjectMapper.insert(sysProject);
                    sysOrgRoleUser.setPositionId(getAdminPosition(Constants.PROJECT_ADMIN));
                    sysOrgRoleUserMapper.insert(sysOrgRoleUser);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return Result.OK;
    }

    @Override
    public Result<Page> findPositionsByOrgId(Map<String, Object> map) {
        Query query = new Query(map);
        query.setRecords(sysOrgMapper.findPositionsByOrgId(query, map));
        return new Result(query, Result.SUCCESS);
    }

    @Override
    public Result findOrgById(Integer id) {
        SysOrg sysOrg = sysOrgMapper.selectById(id);
        if (sysOrg != null) {
            Integer type = sysOrg.getType();
            //如果是公司,园区,和项目,回到相应的表中查询数据
            if (isCompany(type)) {
                return new Result(sysCompanyMapper.selectById(id), Result.SUCCESS);
            } else if (isPark(type)) {
                return new Result(sysParkMapper.selectById(id), Result.SUCCESS);
            } else if (isProject(type)) {
                return new Result(sysProjectMapper.selectById(id), Result.SUCCESS);
            }
            return new Result(sysOrg, Result.SUCCESS);
        }
        return Result.NOT_FOUND;
    }

    @Override
    public Result getDeptTree(Integer userId) {
        Map<String, Object> params = new HashMap<>();
        params.put("delFlag", CommonConstant.STATUS_NORMAL);
        // 超级管理员
        if (!sysRoleService.hasPermission(userId, Constants.SUPER_ADMIN)) {
            // 查询当前用户
            SysUser sysUser = sysUserService.selectById(userId);
            // 政府用户
            if (Constants.TYPE_GOV.equals(sysUser.getType())) {
                // 查询园区节点
                SysOrg sysOrg = this.selectById(sysUser.getOrgId());
                params.put("levelNum", sysOrg.getLevelNum());
            }
            // 企业用户
            else if (Constants.TYPE_COM.equals(sysUser.getType())) {
                // 查询企业节点
                SysOrg sysOrg = this.selectById(sysUser.getOrgId());
                params.put("levelNum", sysOrg.getLevelNum());
            }
        }

        List<SysOrg> sysOrgList = sysOrgMapper.getDeptList(params);

        return new Result(getDeptTree(sysOrgList, null), Result.SUCCESS, "获取成功");

    }

    @Override
    public Result getOrgByUserId(Integer userId) {
        return new Result(sysOrgMapper.findOrgByUserId(userId), Result.SUCCESS);
    }

    private boolean needCreate(Integer type) {
        if (CommonConstant.ORGTYPE_COMP.equals(type)
                || CommonConstant.ORGTYPE_SPARK.equals(type)
                || CommonConstant.ORGTYPE_PROJECT.equals(type)) {
            return true;
        }
        return false;
    }

    private String getUserType(Integer type) {
        if (CommonConstant.ORGTYPE_COMP.equals(type)) {
            return Constants.TYPE_COM;
        } else if (CommonConstant.ORGTYPE_SPARK.equals(type)) {
            return Constants.TYPE_GOV;
        } else if (CommonConstant.ORGTYPE_PROJECT.equals(type)) {
            return Constants.TYPE_COM;
        }
        return null;
    }

    /**
     * 根据code获取position
     *
     * @param roleCode
     * @return
     */
    private Integer getAdminPosition(String roleCode) {
        return sysOrgMapper.findPositionByCode(roleCode);
    }

    private boolean isCompany(Integer type) {
        if (CommonConstant.ORGTYPE_COMP.equals(type)) {
            return true;
        }
        return false;
    }

    private boolean isProject(Integer type) {
        if (CommonConstant.ORGTYPE_PROJECT.equals(type)) {
            return true;
        }
        return false;
    }

    private boolean isPark(Integer type) {
        if (CommonConstant.ORGTYPE_SPARK.equals(type)) {
            return true;
        }
        return false;
    }

    @Override
    public Result getByUserIdAndOrgId(Map<String, Object> map) {
        try {
            Integer userId = Convert.toInt(map.get("userId"));  //用户id
            Integer orgId = Convert.toInt(map.get("orgId"));  //当前选中组织id
            Integer expect = Convert.toInt(map.get("expectType"));  //期望类型,下拉方法中的
            EntityWrapper ew = new EntityWrapper();
            ew.eq("del_flag", CommonConstant.STATUS_NORMAL);
            if (orgId != null) {
                ew.eq("parent_id", orgId);
            }
            if (expect != null) {
                ew.eq("type", expect);
            }
            if (sysRoleService.hasPermission(userId, Constants.SUPER_ADMIN)) {
                //获取所有组织
                List<SysOrg> all = sysOrgMapper.selectList(ew);
                return new Result(all, Result.SUCCESS);
            } else {
                //不是超管,根据人员的orgId获取旗下
                SysOrg sysOrg = sysOrgMapper.findOrgByUserId(userId);
                ew.like("level_num", sysOrg.getLevelNum() + "%");
                List<SysOrg> under = sysOrgMapper.selectList(ew);
                return new Result(under, Result.SUCCESS);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.ERROR;
        }
    }

    @Override
    public Result getOrgTreeByOrgId(Integer orgId) {
        if (orgId == null) {
            return new Result(null, Result.FAIL, "组织id不能为空");
        }
        SysOrg sysOrg = this.selectById(orgId);

        Map<String, Object> params = new HashMap<>();
        params.put("delFlag", CommonConstant.STATUS_NORMAL);
        params.put("levelNum", sysOrg.getLevelNum());

        List<SysOrg> sysOrgList = sysOrgMapper.getDeptList(params);

        return new Result(getDeptTree(sysOrgList, sysOrg.getParentId()), Result.SUCCESS, "获取成功");
    }

    @Override
    public Result getPermissionByUserId(Integer userId) {

        List<SysOrg> parkList = new ArrayList<>();
        SysUser sysUser = sysUserService.selectById(userId);

        List<OrgRelation> resultList = new ArrayList<>();

        // 超级管理员
        if (sysRoleService.hasPermission(userId, Constants.SUPER_ADMIN)) {
            // 查询所有园区
            EntityWrapper ew = new EntityWrapper();
            // 查询园区权限
            ew.eq("del_flag", CommonConstant.STATUS_NORMAL);
            ew.eq("type", CommonConstant.ORGTYPE_SPARK);
            parkList = this.selectList(ew);

        } else {
            // 区分园区和企业
            if (Constants.TYPE_GOV.equals(sysUser.getType())) {
                // 当前园区
                SysOrg park = this.selectById(sysUser.getOrgId());
                parkList.add(park);
            }
            // 企业用户
            else if (Constants.TYPE_COM.equals(sysUser.getType())) {
                // 根据企业id查询所属园区
                // 递归向上查找
                SysOrg park = getTypedOrgByOrgId(sysUser.getOrgId(),CommonConstant.ORGTYPE_SPARK);
                parkList.add(park);
            }
        }

        // 查询园区下企业
        OrgRelation orgRelation;
        List<OrgRelation> children;
        for (SysOrg sysOrg : parkList) {
            children = new ArrayList<>();
            orgRelation = new OrgRelation(sysOrg);
            if (Constants.TYPE_COM.equals(sysUser.getType())) {
                // 如果是企业用户，仅查询自己企业
                SysOrg company = this.selectById(sysUser.getOrgId());
                OrgRelation companyRelation = new OrgRelation(company);
                children.add(companyRelation);
            } else {
                // 如果不是，查询当前园区下面的企业
                EntityWrapper ew = new EntityWrapper();
                ew.where("level_num like concat({0},'%')", sysOrg.getLevelNum());
                ew.eq("del_flag", CommonConstant.STATUS_NORMAL);
                ew.eq("type", CommonConstant.ORGTYPE_COMP);
                List<SysOrg> companyList = this.selectList(ew);
                OrgRelation companyRelation;
                for (SysOrg company : companyList) {
                    children.add(new OrgRelation(company));
                }
            }
            orgRelation.setChildren(children);
            resultList.add(orgRelation);
        }

        return new Result(resultList, Result.SUCCESS, "获取成功");
    }

    @Override
    public SysOrg getTypedOrgByOrgId(Integer orgId, Integer type) {
        SysOrg company = this.selectById(orgId);
        SysOrg condition = new SysOrg();
        condition.setOrgId(company.getParentId());
        condition.setDelFlag(CommonConstant.STATUS_NORMAL);
        SysOrg newSysOrg = this.selectOne(new EntityWrapper<>(condition));
        // 如果是园区返回
        if (type.equals(newSysOrg.getType())) {
            return newSysOrg;
        }
        // 如果已经查询至顶级节点，还没有园区，返回空
        if (CommonConstant.DEFAULT_SPARK_PARENTID.equals(newSysOrg.getType())) {
            return new SysOrg();
        }
        // 递归
        return getTypedOrgByOrgId(newSysOrg.getOrgId(),type);
    }

    @Override
    public List<SysOrg> findByParentIdAndType(Map<String, Object> params) {
        EntityWrapper ew = new EntityWrapper();
        Integer type = Convert.toInt(params.get("type"));
        Integer parentId = Convert.toInt(params.get("parent_id"));
        ew.eq("del_flag", CommonConstant.STATUS_NORMAL);
        if (type != null) {
            ew.eq("type", type);
        }
        if (parentId != null) {
            ew.eq("parent_id", parentId);
        }
        if (AuthRealm.isGov()) {
            ew.eq("org_id", AuthRealm.getPrincipal().getOrgId());
            return sysOrgMapper.selectList(ew);
        }
        if (AuthRealm.isSpAdmin()) {
            return sysOrgMapper.selectList(ew);
        }
        return null;
    }

    @Override
    @Transactional
    public Result<Boolean> delOrg(Map<String, Object> params) {
        Result<Boolean> result = new Result<>();
        Integer id = (Integer) params.get("id");
        // id必须验证
        if (id == null) {
            result.setErrorMessage("id不能为空");
            result.setErrorCode(Result.FAIL);
            return result;
        }
        // 不允许级联删除，查询是否有子项
        SysOrg conditon = new SysOrg();
        conditon.setDelFlag(CommonConstant.STATUS_NORMAL);
        conditon.setParentId(id);
        List<SysOrg> sysOrgs = this.selectList(new EntityWrapper<>(conditon));
        if (sysOrgs != null && sysOrgs.size() > 0) {
            result.setErrorMessage("删除失败 存在子节点");
            result.setErrorCode(Result.FAIL);
            return result;
        }
        SysOrg sysOrg = this.selectById(id);
        sysOrg.setDelFlag(CommonConstant.STATUS_DEL);
        // 验证是否有关联岗位，有则不允许删除
        SysOrgRole position = new SysOrgRole();
        position.setDelFlag(CommonConstant.STATUS_NORMAL);
        position.setOrgId(id);
        List<SysOrgRole> positions = positionService.selectList(new EntityWrapper<>(position));
        if (positions != null && positions.size() > 0) {
            result.setErrorMessage("删除失败 存在关联岗位");
            result.setErrorCode(Result.FAIL);
            return result;
        }

        // 删除
        if (this.updateById(sysOrg)) {
            Integer type = sysOrg.getType();
            if (CommonConstant.ORGTYPE_COMP.equals(type)) {
                sysCompanyService.delete(id);
            } else if (CommonConstant.ORGTYPE_SPARK.equals(type)) {
                sysParkService.delete(id);
            } else if (CommonConstant.ORGTYPE_PROJECT.equals(type)) {
                sysProjectService.delete(id);
            }
            result.setErrorMessage("删除组织架构成功");
            result.setErrorCode(Result.SUCCESS);
        } else {
            result.setErrorMessage("删除组织架构失败");
            result.setErrorCode(Result.FAIL);
        }
        return result;
    }
}
